﻿using System;
using System.Text;
using System.Windows;
using MySqlQueryToolkit.DataAccess;
using MySqlQueryToolkit.Resources;

namespace MySqlQueryToolkit
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            SetUp();
        }

        private void SetUp()
        {
            RunButton.Content = LabelText.Run;
            DatabaseTestConnectionButton.Content = LabelText.Test;

            OptionsTab.Header = LabelText.Options;
            ExplainTab.Header = LabelText.Explain;
            ProfileTab.Header = LabelText.Profile;
            SettingsTab.Header = LabelText.Settings;

            OptionsExplainLabel.Content = LabelText.Explain;
            OptionsProfileLabel.Content = LabelText.Profile;
            OptionsTimeLabel.Content = LabelText.Time;

            DatabaseServerLabel.Content = LabelText.DatabaseServer;
            DatabaseUserLabel.Content = LabelText.DatabaseUser;
            DatabasePasswordLabel.Content = LabelText.DatabasePassword;
        }

        // TODO: List
        // - Take some options about what to run agains the query
        //   - Explain
        //   - Execution Time
        //   - Profile
        //   - ...
        // - Take a query
        //   - If selected, Run explain and display the results nicely
        //   - If selected, run the query and time it (clearing our any caches first!)
        //   - If selected, Profile the query and display the results nicely (clearing our any caches first!)

        private void CheckDatabaseConnection(object sender, RoutedEventArgs e)
        {
            IDataAccess dataAccess = new MySqlDataAccess(GetConnectionString());
            MessageBox.Show(dataAccess.CheckConnection() ? LabelText.DatabaseConnectionOkay : LabelText.DatabaseConnctionFailed);
        }

        private void RunQueryAnalysis(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(QueryInput.Text))
            {
                MessageBox.Show(LabelText.NoQueryEntered);
                return;
            }

            try
            {
                // TODO: perform off the UI thread
                var mainViewData = GetViewData();

                DisplayExplainReport(mainViewData);
                DisplayProfileReport(mainViewData);

                ExplainTab.Focus();

                // TODO: nicely layout data

                // TODO: focus the first tab that has been selected to be output

            } catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void DisplayExplainReport(ViewData mainViewData)
        {
            var stringBuilder = new StringBuilder();
            foreach (var item in mainViewData.ExplainResults)
            {
                stringBuilder.AppendFormat(
                    "id:{0}, selectType:{1}, possibleKeys:{2}, key:{3}, keyLength:{4}, keyRef:{5}, rows:{6}, table:{7}, type:{8}, extra:{9}",
                    item.Id,
                    item.SelectType,
                    item.PossibleKeys,
                    item.Key,
                    item.KeyLength,
                    item.KeyReferencedBy,
                    item.Rows,
                    item.Table,
                    item.Type,
                    item.Extra
                    ).AppendLine();
            }
            ExplainTab.Content = stringBuilder.ToString();
        }

        private void DisplayProfileReport(ViewData mainViewData)
        {
            var profileReportResult = string.Format(
                "HandlerCommit:{0}, HandlerDelete:{1}, HandlerDiscover:{2}, HandlerPrepare:{3}, " +
                "HandlerReadFirst:{4}, HandlerReadKey:{5}, HandlerReadLast:{6}, HandlerReadNext:{7}, " +
                "HandlerReadPrev:{8}, HandlerReadRnd:{9}, HandlerReadRndNext:{10}, HandlerRollback:{11}, " +
                "HandlerSavepoint:{12}, HandlerSavepointRollback:{13}, HandlerUpdate:{14}, HandlerWrite:{15}",
                mainViewData.ProfileResults.HandlerCommit,
                mainViewData.ProfileResults.HandlerDelete,
                mainViewData.ProfileResults.HandlerDiscover,
                mainViewData.ProfileResults.HandlerPrepare,
                mainViewData.ProfileResults.HandlerReadFirst,
                mainViewData.ProfileResults.HandlerReadKey,
                mainViewData.ProfileResults.HandlerReadLast,
                mainViewData.ProfileResults.HandlerReadNext,
                mainViewData.ProfileResults.HandlerReadPrev,
                mainViewData.ProfileResults.HandlerReadRnd,
                mainViewData.ProfileResults.HandlerReadRndNext,
                mainViewData.ProfileResults.HandlerRollback,
                mainViewData.ProfileResults.HandlerSavepoint,
                mainViewData.ProfileResults.HandlerSavepointRollback,
                mainViewData.ProfileResults.HandlerUpdate,
                mainViewData.ProfileResults.HandlerWrite
                );
            ProfileTab.Content = profileReportResult;
        }

        private ViewData GetViewData()
        {
            IDataAccess dataAccess = new MySqlDataAccess(GetConnectionString());
            IUnsafeDataAccess unsafeDataAccess = new UnsafeMySqlDataAccess(GetConnectionString());
            var explainQueryRepository = new ExplainQueryRepository(dataAccess);
            var profileQueryRepository = new ProfileQueryRepository(unsafeDataAccess);
            var timeQueryRepository = new TimeQueryRepository(dataAccess);

            var explainQueryReporter = new ExplainQueryReporter(explainQueryRepository);
            var profileQueryReporter = new ProfileQueryReporter(profileQueryRepository);
            var timeQueryReporter = new TimeQueryReporter(timeQueryRepository);

            var queryHandler = new QueryHandler(explainQueryReporter, profileQueryReporter, timeQueryReporter);

            var shouldExplain = OptionsExplainInput.IsChecked ?? false;
            var shouldProfile = OptionsProfileInput.IsChecked ?? false;
            var shouldTime = OptionsTimeInput.IsChecked ?? false;

            return queryHandler.GetViewData(QueryInput.Text, shouldExplain, shouldProfile, shouldTime);
        }

        private string GetConnectionString()
        {
            return string.Format("Server={0};Uid={1};Pwd={2};port=3306;",
                DatabaseServerInput.Text, 
                DatabaseUserInput.Text, 
                DatabasePasswordInput.Text);
        }
    }
}
